﻿using System.Collections.Concurrent;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace HotSwap.Core;

public static class DomainManage
{
    private static ConcurrentDictionary<string, DomainLoadContextModule> _hotSwapLoadContexts = new();

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static DomainLoadContextModule CreateDomain(string domainName = "DomainManage")
    {
        var domain = new DomainLoadContextModule(new HotSwapLoadContext(domainName), domainName);
        _hotSwapLoadContexts.TryAdd(domain.domainName, domain);
        return domain;
    }

    public static void Unload(this DomainLoadContextModule domainLoadContextModule)
    {
        _hotSwapLoadContexts.Remove(domainLoadContextModule.domainName,out _);
        domainLoadContextModule.HotSwapLoadContext.Unload();
        
        for (int i = 0; domainLoadContextModule.WeakReference.IsAlive && (i < 10); i++)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    public static Assembly LoadFromStream(this DomainLoadContextModule domainLoadContextModule, Stream stream)
    {
        return domainLoadContextModule.HotSwapLoadContext.LoadFromStream(stream);
    }

    public static Assembly LoadFromAssemblyPath(this DomainLoadContextModule domainLoadContextModule, string path)
    {
        return domainLoadContextModule.HotSwapLoadContext.LoadFromAssemblyPath(path);
    }

    public static Assembly LoadFromAssemblyName(this DomainLoadContextModule domainLoadContextModule,
        AssemblyName assemblyName)
    {
        return domainLoadContextModule.HotSwapLoadContext.LoadFromAssemblyName(assemblyName);
    }
}